﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using YJKControls.Previewer;

namespace YJKArch.Utils
{
	public class LegendCommon
	{
		public static Legend GetFamily2DImg(UIApplication uiApp, Autodesk.Revit.DB.Document sourceDocument, LegendType type)
		{
			Legend result;
			try
			{
				Legend legend = new Legend();
				List<CurveInfo> list = new List<CurveInfo>();
				Autodesk.Revit.DB.View referenceView = LegendCommon.GetReferenceView(sourceDocument);
				if (referenceView == null)
				{
					result = null;
				}
				else
				{
					List<Element> list2 = new List<Element>();
					List<Element> list3 = new List<Element>();
					Element element = null;
					foreach (Element element2 in new FilteredElementCollector(sourceDocument, referenceView.Id).ToElements())
					{
						if (element2.Category != null)
						{
							if (element2 is SymbolicCurve)
							{
								list2.Add(element2);
							}
							else if (element2 is FamilyInstance)
							{
								if (element2.Category.Id.IntegerValue == -2000023 || element2.Category.Id.IntegerValue == -2000014 || element2.Category.Id.IntegerValue == -2000100 || element2.Category.Id.IntegerValue == -2002000)
								{
									list3.Add(element2);
								}
							}
							else if (element2 is Wall)
							{
								element = element2;
							}
						}
					}
					foreach (Element element3 in list2)
					{
						try
						{
							int num = element3.get_Parameter(BuiltInParameter.CURVE_VISIBILITY_PARAM).AsInteger();
							if (LegendCommon.IsSymbolicCurveCoarse(num) && num != -1)
							{
								Curve curve = (element3.Location as LocationCurve).Curve;
								if (curve.IsBound)
								{
									list.Add(new CurveInfo(curve, PenColor.PC_Black, 1f));
								}
							}
						}
						catch (Exception)
						{
						}
					}
					Options options = new Options();
					options.View = uiApp.ActiveUIDocument.ActiveView;
					options.ComputeReferences = true;
					if (list.Count == 0)
					{
						foreach (Element element4 in list3)
						{
							bool flag = false;
							if (element4.Category.Id.IntegerValue == -2002000)
							{
								int num2 = element4.get_Parameter(BuiltInParameter.CURVE_VISIBILITY_PARAM).AsInteger();
								if (LegendCommon.IsSymbolicCurveCoarse(num2) && num2 != -1)
								{
									flag = true;
								}
							}
							else
							{
								int num3 = element4.get_Parameter(BuiltInParameter.GEOM_VISIBILITY_PARAM).AsInteger();
								if (LegendCommon.IsCoarse(num3) && num3 != -1)
								{
									flag = true;
								}
							}
							if (flag)
							{
								List<GeometryObject> list4 = new List<GeometryObject>();
								foreach (GeometryObject item in (element4 as FamilyInstance).Symbol.get_Geometry(options))
								{
									list4.Add(item);
								}
								foreach (GeometryObject geometryObject in list4)
								{
									if (geometryObject is Arc || geometryObject is Line)
									{
										Curve curve2 = (Curve)geometryObject;
										if (curve2.IsBound)
										{
											list.Add(new CurveInfo(curve2, PenColor.PC_Black, 1f));
										}
									}
									else if (geometryObject is Solid)
									{
										Solid solid = geometryObject as Solid;
										if (!(solid == null))
										{
											foreach (object obj in solid.Edges)
											{
												Curve curve2 = ((Edge)obj).AsCurve();
												if (curve2.IsBound)
												{
													list.Add(new CurveInfo(curve2, PenColor.PC_Black, 1f));
												}
											}
										}
									}
								}
							}
						}
					}
					if (element != null)
					{
						list = LegendCommon.GetWallCurves(list, element);
					}
					if (type == LegendType.Column)
					{
						LegendCommon.ColumnExtension(sourceDocument, referenceView, options, ref list);
					}
					legend.Curves = list;
					if (list.Count == 0)
					{
						result = null;
					}
					else
					{
						result = legend;
					}
				}
			}
			catch (Exception)
			{
				result = null;
			}
			return result;
		}

		private static List<CurveInfo> GetWallCurves(List<CurveInfo> curves, Element wall)
		{
			List<XYZ> list = new List<XYZ>();
			Line line = (wall.Location as LocationCurve).Curve as Line;
			XYZ endPoint = line.GetEndPoint(0);
			XYZ endPoint2 = line.GetEndPoint(1);
			foreach (CurveInfo curveInfo in curves)
			{
				Curve curveObj = curveInfo.CurveObj;
				XYZ xyzpoint = line.Project(curveObj.GetEndPoint(0)).XYZPoint;
				XYZ xyzpoint2 = line.Project(curveObj.GetEndPoint(1)).XYZPoint;
				list.Add(xyzpoint);
				list.Add(xyzpoint2);
				IntersectionResultArray intersectionResultArray;
				if (Line.CreateBound(new XYZ(endPoint.X, endPoint.Y, curveObj.GetEndPoint(0).Z), new XYZ(endPoint2.X, endPoint2.Y, curveObj.GetEndPoint(0).Z)).Intersect(curveObj, out intersectionResultArray) == SetComparisonResult.Overlap)
				{
					foreach (object obj in intersectionResultArray)
					{
						IntersectionResult intersectionResult = (IntersectionResult)obj;
						list.Add(intersectionResult.XYZPoint);
					}
				}
			}
			list.Sort(new X_CoordinateComparer());
			XYZ pt = list[0];
			XYZ pt2 = list[list.Count - 1];
			LegendCommon.DrawWallLine(wall, line, pt, ref curves, false);
			LegendCommon.DrawWallLine(wall, line, pt2, ref curves, true);
			return curves;
		}

		private static Autodesk.Revit.DB.View GetReferenceView(Autodesk.Revit.DB.Document sourceDocument)
		{
			FilteredElementIterator elementIterator = new FilteredElementCollector(sourceDocument).OfClass(typeof(Autodesk.Revit.DB.View)).GetElementIterator();
			elementIterator.Reset();
			Autodesk.Revit.DB.View view = null;
			while (elementIterator.MoveNext())
			{
				Element element = elementIterator.Current;
				Autodesk.Revit.DB.View view2 = element as Autodesk.Revit.DB.View;
				if (view2 != null && !view2.IsTemplate && (int)view2.ViewType == 1)
				{
					view = view2;
					break;
				}
			}
			if (view == null)
			{
				while (elementIterator.MoveNext())
				{
					Element element2 = elementIterator.Current;
					Autodesk.Revit.DB.View view3 = element2 as Autodesk.Revit.DB.View;
					if (view3 != null && !view3.IsTemplate && (int)view3.ViewType == 2)
					{
						view = view3;
						break;
					}
				}
			}
			return view;
		}

		private static void ColumnExtension(Autodesk.Revit.DB.Document sourceDocument, Autodesk.Revit.DB.View view, Options options, ref List<CurveInfo> curves)
		{
			List<Element> list = new List<Element>();
			foreach (Element element in new FilteredElementCollector(sourceDocument, view.Id).ToElements())
			{
				if (element is Extrusion)
				{
					list.Add(element);
				}
			}
			foreach (Element element2 in list)
			{
				GeometryElement geometryElement = element2.get_Geometry(options);
				List<GeometryObject> list2 = new List<GeometryObject>();
				foreach (GeometryObject item in geometryElement)
				{
					list2.Add(item);
				}
				foreach (GeometryObject geometryObject in list2)
				{
					if (geometryObject is Solid)
					{
						foreach (object obj in (geometryObject as Solid).Faces)
						{
							PlanarFace planarFace = ((Face)obj) as PlanarFace;
							if (planarFace != null && planarFace.FaceNormal().IsAlmostEqualTo(XYZ.BasisZ))
							{
								foreach (object obj2 in planarFace.EdgeLoops)
								{
									foreach (object obj3 in ((EdgeArray)obj2))
									{
										Curve curve = ((Edge)obj3).AsCurve();
										if (Geometry.IsEqual(curve.GetEndPoint(0).Z, curve.GetEndPoint(1).Z) && curve.IsBound)
										{
											curves.Add(new CurveInfo(curve, PenColor.PC_Black, 1f));
										}
									}
								}
							}
						}
					}
				}
			}
		}

		private static void DrawWallLine(Element wall, Line line, XYZ pt, ref List<CurveInfo> lcs, bool isRight = false)
		{
			double num = (wall as Wall).Width / 2.0;
			double num2 = 3.0;
			XYZ xyz;
			XYZ xyz2;
			XYZ xyz3;
			XYZ xyz4;
			if (!isRight)
			{
				xyz = pt + XYZ.BasisY * num;
				xyz2 = pt + -XYZ.BasisY * num;
				xyz3 = xyz + -XYZ.BasisX * num2;
				xyz4 = xyz2 + -XYZ.BasisX * num2;
			}
			else
			{
				xyz3 = pt + XYZ.BasisY * num;
				xyz4 = pt + -XYZ.BasisY * num;
				xyz = xyz3 + XYZ.BasisX * num2;
				xyz2 = xyz4 + XYZ.BasisX * num2;
			}
			lcs.Add(new CurveInfo(Line.CreateBound(xyz3, xyz), PenColor.PC_Black, 1f));
			lcs.Add(new CurveInfo(Line.CreateBound(xyz4, xyz2), PenColor.PC_Black, 1f));
			lcs.Add(new CurveInfo(Line.CreateBound(xyz3, xyz4), PenColor.PC_Black, 1f));
			lcs.Add(new CurveInfo(Line.CreateBound(xyz, xyz2), PenColor.PC_Black, 1f));
		}

		private static bool IsCoarse(int value)
		{
			return (value & 8206) == 8206;
		}

		private static bool IsSymbolicCurveCoarse(int value)
		{
			return (value & 8192) == 8192;
		}
	}
}
